package edzest.basic;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class J18_JDBCSetup {
	
	// JDBC 접속 정보
	private static final String DRV = "oracle.jdbc.OracleDriver";
	private static final String URL = "jdbc:oracle:thin:@//localhost:1521/xe";
	private static final String USR = "scott";
	private static final String PWD = "TIGER";
	
	// SQL 문 작성
	private static final String insertSQL = "insert into SUNGJUK(sjno, name, kor, eng, mat) "
			+ " VALUES(SJNO.nextval,'혜교',78,45,12)";
	// String에 대해서 잘 알게 되면 끊어 쓸때 +연산으로 스트링 연결하면 메모리 소모가 되서 안좋다는 걸 알게 됨
	// 이를 보완하기위해 스트링버퍼 스트링빌더 사용
	// SQL문은 한칸 띄우지않고 한줄로 쓰는게 좋으나 정 띄어야겠다면 +연산자로 연결할 때 한 칸 띄우고 연결. 
	private static final String selectSQL = "select * from sungjuk order by sjno desc";

	public static void main(String[] args) {
		// 오라클을 이용한 JDBC 프로그래밍 기초
		// 1. JDBC 드라이버를 메모리에 적재하여 
		//    객체로 생성하고 이것을 DriverManager에 등록
		
		// 2. DriverManager의 getConnection 메서드를
		//    이용해서 데이터베이스 연결객체를 생성함
		//-------- 1, 2까지는 cmd창에서 sqlplus를 실행하는 과정이랑 같다고 보면됨
		
		// 3. PreparedStatement로 실행할 SQL문 객체를 생성
		//    PreparedStatement를 사용하면 SQL문이 캐시에 남아서
		//    다시 실행시 컴파일하지 않고 실행
		
		// 4a. 실행하는 SQL문이 insert, update, delete라면
		// 	   executeUpdate()를 사용하고
		//     실행결과는 변경된 행의 갯수를 int 로 받음
		
		// 4b. 실행하는 SQL문이 select라면
		//	   executeQuery()를 사용하고
		//     실행결과는 ResultSet(결과집합 객체)으로 받음
		
		// 5. ResultSet으로 받은 결과 테이블은
		//    먼저 rs.next() 로 읽어올 레코드를 가리킨 후
		//	  rs.getXXX ( 필드번호 ) 또는
		//    rs.getXXX ( 필드이름 ) 으로
		//    테이블의 각 필드 값을 처리할 수 있음
		
		// 6. JDBC 작업이 끝나면
		//    데이터베이스 접속을 끊고
		//    관련객체 (conn, ps, rs)는
		//    메모리에서 제거함
		
		// 밑에 3줄은 기계적으로 작성
		// null은 객체저장할 주소만 만들고 실제 객체는 안넣은 상태
		Connection conn = null; // 연결객체 저장용
		PreparedStatement ps = null; // SQL 객체
		ResultSet rs = null; // 실행결과 저장용
		
		try{
			Class.forName( DRV );  // 1. 일반 객체생성은 정적객체생성, 이 방식은 동적객체생성
			conn = DriverManager.getConnection(URL, USR, PWD); // 2. URL, USR, PWD를 넣고 연결객체를 반환
			
			ps = conn.prepareStatement( insertSQL );
			int cnt = ps.executeUpdate(); // 4a.
			System.out.println( cnt + "건의 데이터 입력" );
			
			ps.close();  // 또다른 SQL문 작성하기 위해
						 // 기존 ps 객체 제거
			ps = conn.prepareStatement( selectSQL ); // 기존 SQL문 객체 제거하고 다시 SQL문 실행하기 위해 ps객체 만듬
			rs = ps.executeQuery(); // 4b.
			
			// ResultSet에서 결과를 레코드 단위로 꺼내
			// 차례대로 출력
			while(rs.next()) {  // 5.
				// ResultSet에서 읽어올 레코드가 있으면
				System.out.println( rs.getInt(1) ); // 첫번째 컬럼을 가져와라
				// System.out.println( rs.getInt("name") );
				// java.sql.SQLException
				System.out.println( rs.getString("name") ); // name컬럼을 가져와라, 대부분 getString 정확한 컬럼이름 입력해주는게 깔끔하니까
			}
			
		} catch(Exception ex){
			ex.printStackTrace();
		} finally {
			// 6.
			// JDBC 작업이 끝난후 메모리에서 객체 제거
			if( rs != null ) // rs에 더이상 행이 없으면
				try {
					rs.close(); // rs객체를 메모리에서 제거
				} catch (SQLException e) {
					e.printStackTrace();
				} 
			if( ps != null )
				try {
					ps.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}
			if( conn != null )
				try {
					conn.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}
		}
	}

}
